package net.p2pcdn.user.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qc.bean.result.Paging;
import com.qc.bean.result.ResponseData;
import net.p2pcdn.email.domain.EmailType;
import net.p2pcdn.email.service.DefaultEmailSender;
import net.p2pcdn.user.domain.Role;
import net.p2pcdn.user.domain.User;
import net.p2pcdn.user.domain.UserRole;
import net.p2pcdn.user.repository.RoleRepository;
import net.p2pcdn.user.repository.UserRepository;
import net.p2pcdn.user.repository.UserRoleRepository;
import net.p2pcdn.util.MD5Util;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class UserService implements InitializingBean {
    private final static String DEFAULT_SYSTEM_USERNAME = "admin";
    @Resource
    private UserRepository userRepository;
    @Resource
    private UserRoleRepository userRoleRepository;
    @Resource
    private RoleRepository roleRepository;
    @Autowired
    private DefaultEmailSender defaultEmailSender;

    public void initSystemAdmin() {
        User user = userRepository.findByUsername(DEFAULT_SYSTEM_USERNAME);
        if (user == null) {
            user = new User(DEFAULT_SYSTEM_USERNAME, "1004098214@qq.com", MD5Util.encryption("123456"));
            user.setEmailValid(true);
            userRepository.insert(user);
            bindCustomRole(user.getId(), Role.ROLE_SUPER_ADMIN);
        }
    }

    @Override
    public void afterPropertiesSet() {
        this.initSystemAdmin();
    }

    /**
     * 添加用户
     *
     * @param email
     * @param password
     * @param roleCodes
     */
    public void addUser(String email, String password, String roleCodes) {
        User user = this.userRepository.findByUsername(email);
        if (user != null) {
            throw new RuntimeException("用户已存在，换一个邮箱试试");
        }
        user = new User(email, email, MD5Util.encryption(password));
        bindCustomRole(user.getId(), StringUtils.isNotBlank(roleCodes) ? roleCodes.split(",") : null);
    }

    private void bindDefaultRole(int userId) {
        Role role = roleRepository.findByCode(Role.ROLE_USER);
        UserRole userRole = new UserRole(userId, role.getId());
        userRoleRepository.insert(userRole);
    }

    public void bindCustomRole(int userId, String... roleCode) {
        if (roleCode != null) {
            List<String> roles = Stream.of(roleCode).collect(Collectors.toList());
            roles.remove(Role.ROLE_USER);
            for (String code : roles) {
                Role superRole = roleRepository.findByCode(code);
                if (superRole == null) {
                    throw new RuntimeException("database base data not init");
                }
                UserRole userRole = new UserRole(userId, superRole.getId());
                userRoleRepository.insert(userRole);
            }
        }
        bindDefaultRole(userId);
    }

    public void updateUser(int userId, String email, String password, String roleIds, Boolean locked) {
        User user = userRepository.selectByPrimaryKey(userId);
        if (StringUtils.isNotBlank(email)) {
            user.setEmail(email);
        }
        if (StringUtils.isNotBlank(password)) {
            user.setPassword(MD5Util.encryption(password));
        }
        if (locked != null) {
            user.setLocked(locked);
        }
        if (StringUtils.isNotBlank(roleIds)) {
            userRoleRepository.deleteByUserId(userId);
            for (String rid : roleIds.split(",")) {
                UserRole userRole = new UserRole(userId, Integer.parseInt(rid));
                this.userRoleRepository.insert(userRole);
            }
        }
        this.userRepository.updateByPrimaryKey(user);
    }

    public void deleteUser(int userId) {
        userRoleRepository.deleteByUserId(userId);
        userRepository.deleteByPrimaryKey(userId);
    }

    public Paging<User> queryUsers(String email, String roleCodes, Boolean locked, int page, int size) {
        PageHelper.startPage(page, size);
        Map<String, Object> params = new HashMap<>();
        params.put("email", email);
        if(StringUtils.isNotBlank(roleCodes)){
            if(roleCodes.contains(",")){
                params.put("roleCodes", Stream.of(roleCodes.split(",")).collect(Collectors.toList()));
            }else{
                params.put("roleCode", roleCodes);
            }
        }
        params.put("locked", locked);
        List<User> list = userRepository.query(params);
        PageInfo<User> pageInfo = new PageInfo<>(list);
        return new Paging<>((int) pageInfo.getTotal(), pageInfo.getList());
    }

    public void sendRegisterEmailCode(String email) {
        String subject = "P2PCDN注册-邮件验证码";
        String code = RandomStringUtils.random(6, "9083265417");
        String content = "尊敬的用户您好，您的验证码是【" + code + "】,10内输入有效，请勿告知他人。";
        defaultEmailSender.send(email, subject, EmailType.REG, content, code);
    }


    public ResponseData register(String email, String checkCode, String password) {
        boolean valid = defaultEmailSender.validate(email, checkCode, EmailType.REG, 10);
        if (!valid) {
            return ResponseData.error("邮箱验证码输入错误", 500);
        }
        User user = this.userRepository.findByUsername(email);
        if (user != null) {
            return ResponseData.error("邮箱地址已被注册，请您更换一个邮箱地址", 500);
        }
        user = new User(email, email, MD5Util.encryption(password));
        user.setEmailValid(true);
        this.userRepository.insert(user);
        bindCustomRole(user.getId(), Role.ROLE_CUSTOMER_ADMIN);
        user.setPassword("");
        return ResponseData.success(user);
    }

    public ResponseData sendForgetPasswordEmailCode(String email) {
        User user = this.userRepository.findByUsername(email);
        if (user == null) {
            return ResponseData.error("邮箱未注册", 500);
        }
        String subject = "P2PCDN找回密码-邮件验证码";
        String code = RandomStringUtils.random(6, "9083265417");
        String content = "尊敬的用户您好，您的验证码是【" + code + "】,10内输入有效，请勿告知他人。";
        defaultEmailSender.send(email, subject, EmailType.RESET_PASSWORD, content, code);
        return ResponseData.success("ok");
    }

    public ResponseData forgetPassword(String email, String emailCode, String newPassword) {
        User user = this.userRepository.findByUsername(email);
        if (user == null) {
            return ResponseData.error("邮箱未注册", 500);
        }
        boolean valid = defaultEmailSender.validate(email, emailCode, EmailType.RESET_PASSWORD, 10);
        if (!valid) {
            return ResponseData.error("验证码错误", 500);
        }
        user.setPassword(MD5Util.encryption(newPassword));
        user.setUpdateTime(new Date());
        user.setEmailValid(true);
        this.userRepository.updateByPrimaryKey(user);
        return ResponseData.success("ok");
    }

    public ResponseData sendUpdatePasswordEmailCode(int userId) {
        User user = this.userRepository.selectByPrimaryKey(userId);
        String subject = "P2PCDN修改密码-邮件验证码";
        String code = RandomStringUtils.random(6, "9083265417");
        String content = "尊敬的用户您好，您的验证码是【" + code + "】,10内输入有效，请勿告知他人。";
        defaultEmailSender.send(user.getEmail(), subject, EmailType.UPDATE_PASSWORD, content, code);
        return ResponseData.success("ok");
    }

    public ResponseData updatePassword(int userId,String emailCode,String oldPassword,String password) {
        User user = this.userRepository.selectByPrimaryKey(userId);
        boolean valid = defaultEmailSender.validate(user.getEmail(), emailCode, EmailType.UPDATE_PASSWORD, 10);
        if (!valid) {
            return ResponseData.error("验证码错误", 500);
        }
        String op = MD5Util.encryption(oldPassword);
        if(!op.equals(user.getPassword())){
            return ResponseData.error("旧密码不正确", 500);
        }
        user.setPassword(MD5Util.encryption(password));
        user.setUpdateTime(new Date());
        this.userRepository.updateByPrimaryKey(user);
        return ResponseData.success("ok");
    }

    public void changePassword(int userId, String oldPassword, String newPassword) {
        User user = this.userRepository.selectByPrimaryKey(userId);
        if (MD5Util.encryption(oldPassword).equals(user.getPassword())) {
            user.setPassword(MD5Util.encryption(newPassword));
            user.setUpdateTime(new Date());
            this.userRepository.updateByPrimaryKey(user);
        } else {
            throw new RuntimeException("旧密码错误");
        }
    }

    public List<UserRole> getUserRoles(int userId) {
        return userRoleRepository.findByUserId(userId);
    }

    public User findByUsername(String username) {
        return this.userRepository.findByUsername(username);
    }

    public User getById(int userId) {
        return userRepository.selectByPrimaryKey(userId);
    }

    public List<Role> findAllRoles() {
        return this.roleRepository.findAll();
    }

    public void addRole(Integer roleId, String code, String name) {
        if (roleId == null) {
            Role exist = roleRepository.findByCode(code);
            if (exist != null) {
                throw new RuntimeException("角色编码已存在");
            }
            exist = new Role(code, name);
            this.roleRepository.insert(exist);
        } else {
            Role exist = roleRepository.selectByPrimaryKey(roleId);
            if (!exist.getCode().equals(code)) {
                if (roleRepository.findByCode(code) != null) {
                    throw new RuntimeException("角色编码已存在");
                }
                exist.setCode(code);
            }
            exist.setName(name);
            this.roleRepository.updateByPrimaryKey(exist);
        }
    }

    public void deleteRole(int roleId) {
        roleRepository.deleteByPrimaryKey(roleId);
    }

    public Role getRole(int roleId) {
        return roleRepository.selectByPrimaryKey(roleId);
    }

    public void removeUserRole(int userId, int roleId) {
        this.userRoleRepository.deleteByUserIdAndRoleId(userId,roleId);
    }

    public void updateRole(int roleId, String code, String name) {
        Role role = this.roleRepository.selectByPrimaryKey(roleId);
        role.setCode(code);
        role.setName(name);
        this.roleRepository.updateByPrimaryKey(role);
    }

    public void saveRole(String code, String name) {
        Role role = new Role(code,name);
        this.roleRepository.insert(role);
    }
}
